home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / iobounce.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.1 KB  |  347 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /* 
  18.  *  iobounce:  an openGL-Xlib 2-D animation program.
  19.  *
  20.  *           iobounce is the openGL "after" version of the IrisGL
  21.  *           "before" program, ~4Dgifts/examples/grafix/iobounce.c.
  22.  *
  23.  *                RIGHTMOUSE  stops ball
  24.  *                MIDDLEMOUSE increases y velocity
  25.  *                LEFTMOUSE   increases x velocity
  26.  *
  27.  *   iobounce is a "pool ball" that "bounces" around a 2-d "surface". 
  28.  *
  29.  *                                   ratmandu -- ported to openGL, april '93
  30.  */
  31.  
  32. #include <GL/glx.h>
  33. #include <GL/gl.h>
  34. #include <GL/glu.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <X11/keysym.h>
  38. #include <X11/Xlib.h>
  39. #include <X11/Xutil.h>
  40.  
  41. #define XMIN 100
  42. #define YMIN 100
  43. #define XMAX 900
  44. #define YMAX 700
  45.  
  46. #define BLACK           0
  47. #define YELLOW          3
  48.  
  49. #define LEFTMOUSE       3
  50. #define MIDDLEMOUSE     2
  51. #define RIGHTMOUSE      1
  52.  
  53. #define TRUE            1
  54. #define FALSE           0
  55.  
  56. long xmaxscrn, ymaxscrn;         /* maximum size of screen in x and y       */
  57.  
  58. Display *dpy;                                    /* The X server connection */
  59. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  60. Window glwin;                                    /* handle to the GL window */
  61. XEvent event;
  62.  
  63. static void openwindow(char *);
  64. static void drawball(void);
  65. static void clean_exit(void);
  66.  
  67. long xvelocity = 0, yvelocity = 0;
  68.  
  69. main(int argc, char *argv[])
  70. {
  71.     int myExpose, myConfigure,
  72.     myButtRelease, myKeyPress,
  73.         myButtonNumber;                         /* store which events occur */
  74.     long xsize, ysize;
  75.  
  76.  
  77.  
  78.     myExpose = myConfigure = myButtRelease = myKeyPress = FALSE;
  79.  
  80.     openwindow(argv[0]);
  81.  
  82.     while (TRUE) {
  83.  
  84.         KeySym keysym;
  85.         char buf[4];
  86.  
  87.     /* this "do while" loop does the `get events' half of the "get events,
  88.      *  process events" action of the infinite while.  this is to ensure
  89.      *  the event queue is always drained before the events that have come
  90.      *  in are processed.
  91.      */
  92.         while (XEventsQueued(dpy,QueuedAfterReading)) { 
  93.                                    /* XEventsQueued(dpy,QueuedAfterReading) is 
  94.                     * like qtest()--it only tells you if 
  95.                     * there're any events presently in the 
  96.                     * queue.  it does not disturb the event
  97.                     * queue's contents in any way.
  98.                                     */
  99.  
  100.             XNextEvent(dpy, &event);
  101.             switch (event.type) {
  102.  
  103.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  104.              *  terms of when a window becomes visible, or a previously
  105.              *  invisible part becomes visible.
  106.              */
  107.                 case Expose:                        /* Exposures */
  108.                     myExpose = TRUE;
  109.                     break;
  110.  
  111.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  112.              *   to a window's size or position.
  113.              */
  114.                 case ConfigureNotify:                /* Resize GL manually */
  115.                     xsize = event.xconfigure.width;
  116.                     ysize = event.xconfigure.height;
  117.                     myConfigure = TRUE;
  118.                     break;
  119.  
  120.             /* Wait for "ButtonRelease" events so the queue doesn't fill up
  121.              *  the way it wud if the user sits on ButtonPresss.
  122.              */
  123.                 case ButtonRelease:
  124.                     if (event.xbutton.button == Button1) {  
  125.                         myButtonNumber = LEFTMOUSE;        
  126.                         myButtRelease = TRUE;             
  127.                     } else if (event.xbutton.button == Button2) {
  128.                         myButtonNumber = MIDDLEMOUSE;
  129.                         myButtRelease = TRUE;      
  130.                     } else if (event.xbutton.button == Button3) {
  131.                         myButtonNumber = RIGHTMOUSE;
  132.                         myButtRelease = TRUE; 
  133.                     }                            /* twirl the green sphere */
  134.                     break;
  135.  
  136.             /* "ClientMessage" is generated if the WM itself is being
  137.              *  gunned down and sends an exit signal to any running prog.
  138.              */
  139.                 case ClientMessage:
  140.                     if (event.xclient.data.l[0] == del_atom)
  141.                         clean_exit();
  142.                     break;
  143.  
  144.  
  145.             /* "KeyPress" events are those that would be generated before
  146.              *   whenever queueing up any KEYBD key via qdevice.
  147.              */
  148.                 case KeyPress:
  149.                    /* save out which unmodified key (i.e. the  key was
  150.                     *  not modified w/something like "Shift", "Ctrl",
  151.                     *  or "Alt") got pressed for use below.
  152.                     */
  153.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  154.                     myKeyPress = TRUE;
  155.                     break;
  156.  
  157.             }  /* end switch (event.type) */
  158.         }  /* end while (XEventsQueued(dpy,QueuedAfterReading)) { */
  159.  
  160.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  161.      */
  162.         if (myExpose) {
  163.             drawball();                               /* draw the GL stuff */
  164.             myExpose = FALSE;               /* reset flag--queue now empty */
  165.         }
  166.  
  167.  
  168.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  169.      *  resized.  Respond accordingly and then redraw its contents.
  170.      */
  171.         if (myConfigure) {
  172.             glViewport(0, 0, xsize, ysize);
  173.         glLoadIdentity();
  174.             gluOrtho2D(XMIN-0.5, XMAX+0.5, YMIN-0.5, YMAX+0.5);
  175.             drawball();                               /* draw the GL stuff */
  176.             myConfigure = FALSE;            /* reset flag--queue now empty */
  177.         }
  178.  
  179.     /* On a "ButtonRelease" event, myButtonNumber stores which mouse button
  180.      * was pressed/released and then we update x/yvelocity accordingly
  181.      */
  182.         if (myButtRelease) {
  183.             if (myButtonNumber == LEFTMOUSE) {       /* increase xvelocity */
  184.                 if (xvelocity >= 0)
  185.                     xvelocity += 3;
  186.                 else
  187.                     xvelocity -= 3;
  188.             } else if (myButtonNumber == MIDDLEMOUSE) {/*increase yvelocity*/
  189.                 if (yvelocity >= 0)
  190.                     yvelocity += 3;
  191.                 else
  192.                     yvelocity -= 3;
  193.             } else if (myButtonNumber == RIGHTMOUSE) {        /* stop ball */
  194.                 xvelocity = yvelocity = 0;
  195.             } else {
  196.                 fprintf(stderr,"ERROR: %s thinks mouse button # ");
  197.         fprintf(stderr,"%d was pressed(?)\n",argv[0],myButtonNumber);
  198.         }
  199.             drawball();
  200.             myButtRelease = FALSE;
  201.         }
  202.  
  203.         /* On a keypress of Esc key, exit program.
  204.          */
  205.         if (myKeyPress) {
  206.             if (keysym == XK_Escape)
  207.                 clean_exit();
  208.         }
  209.         drawball();
  210.  
  211.     }
  212. }
  213.  
  214.  
  215. static int attributeList[] = { GLX_DOUBLEBUFFER, 
  216.                                None };
  217. GLUquadricObj *qobj; 
  218.  
  219. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  220.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  221. }
  222.  
  223. static void 
  224. openwindow(char *progname) 
  225. {
  226.     int scrnnum;                               /* X screen number            */
  227.     int xorig, yorig;                          /* window (upper-left) origin */
  228.     XVisualInfo *vi;
  229.     GLXContext cx;
  230.     Colormap cmap;
  231.     XSizeHints Winhints;                          /* used to fix window size */
  232.     XSetWindowAttributes swa;
  233.     XColor colorstruct;
  234.  
  235.  
  236.     /* Connect to the X server and get screen info */
  237.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  238.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  239.                                  progname, XDisplayName(NULL));
  240.         exit(1);
  241.     }
  242.     scrnnum = DefaultScreen(dpy);
  243.     ymaxscrn = DisplayHeight(dpy, scrnnum);
  244.     xmaxscrn = DisplayWidth(dpy, scrnnum);
  245.  
  246.     /* get an appropriate visual */
  247.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  248.     if (vi == NULL) {
  249.     printf("Couldn't get visual.\n");
  250.     exit(0);
  251.     }
  252.  
  253.     /* create a GLX context */
  254.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  255.     if (cx == NULL) {
  256.     printf("Couldn't get context.\n");
  257.     exit(0);
  258.     }
  259.  
  260.     /* create a colormap */
  261.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  262.                            vi->visual, AllocAll);
  263.  
  264.     XSync(dpy, 0);
  265.     /* create a window */
  266.     swa.colormap = cmap;
  267.     swa.border_pixel = 0;
  268.  
  269.     /* express interest in certain events */
  270.     swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask |
  271.                ButtonReleaseMask | ExposureMask;
  272.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 
  273.                           10, 10, 300, 300,
  274.                           0, vi->depth, InputOutput, vi->visual,
  275.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  276.  
  277.     XMapWindow(dpy, glwin);
  278.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  279.  
  280.     /* connect the context to the window */
  281.     glXMakeCurrent(dpy, glwin, cx);
  282.  
  283.    /* express interest in WM killing this app */
  284.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  285.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  286.  
  287.     colorstruct.pixel = BLACK;    
  288.     colorstruct.red   = 0;
  289.     colorstruct.green = 0;
  290.     colorstruct.blue  = 0;
  291.     colorstruct.flags = DoRed | DoGreen | DoBlue;
  292.     XStoreColor(dpy, cmap, &colorstruct);
  293.     colorstruct.pixel = YELLOW;
  294.     colorstruct.red   = 65535;
  295.     colorstruct.green = 65535;
  296.     colorstruct.blue  = 0;
  297.     colorstruct.flags = DoRed | DoGreen | DoBlue;
  298.     XStoreColor(dpy, cmap, &colorstruct);
  299.  
  300.     glLoadIdentity();
  301.     gluOrtho2D(XMIN - 0.5,  XMAX + 0.5,  YMIN - 0.5,  YMAX + 0.5);
  302.  
  303.     /* clear the buffer */
  304.     glClearIndex((GLfloat)BLACK);
  305.     qobj = gluNewQuadric(); 
  306.     gluQuadricDrawStyle(qobj,GLU_FILL);
  307.     glFlush();
  308. }
  309.  
  310.  
  311. static void 
  312. drawball(void) 
  313. {
  314.     static int xpos = 500, ypos = 500;
  315.     GLdouble radius = 14.0;
  316.  
  317.  
  318.     glClear(GL_COLOR_BUFFER_BIT);
  319.     xpos += xvelocity;
  320.     ypos += yvelocity;
  321.     if (xpos > XMAX - radius || xpos < XMIN + radius) {
  322.         xpos -= xvelocity;
  323.         xvelocity = -xvelocity;
  324.     }
  325.     if (ypos > YMAX - radius || ypos < YMIN + radius) {
  326.         ypos -= yvelocity;
  327.         yvelocity = -yvelocity;
  328.     }
  329.     glIndexi(YELLOW);
  330.     glPushMatrix(); 
  331.     glTranslatef(xpos,  ypos, 0.); 
  332.     gluDisk( qobj, 0., radius, 10, 1); 
  333.     glPopMatrix(); 
  334.     glXSwapBuffers(dpy, glwin);
  335. }
  336.  
  337.  
  338. /*  clean_exit  --  Clean up before exiting
  339.  */
  340. static void 
  341. clean_exit(void)
  342. {
  343.     gluDeleteQuadric(qobj); 
  344.     XCloseDisplay(dpy);
  345.     exit(0);
  346. }
  347.